﻿// DlgCalibration.cpp : 구현 파일입니다.
//

#include "stdafx.h"
#include "MtCtrl.h"
#include "MtCtrlDlg.h"
#include "DlgCalibration.h"
#include "afxdialogex.h"
#include "MemDC2.h"
#include <math.h>


// CDlgCalibration 대화 상자입니다.

IMPLEMENT_DYNAMIC(CDlgCalibration, CDialogEx)
	CDlgCalibration::CDlgCalibration(CWnd* pParent /*=NULL*/)
	: CDialogEx(CDlgCalibration::IDD, pParent)
{
	m_nCalibrationStep = CALIBRATION_NONE;
	m_nMovingAverageCount = 0;
	m_nScreenRadianIndex = 0;
}

CDlgCalibration::~CDlgCalibration()
{
}

void CDlgCalibration::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CDlgCalibration, CDialogEx)
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_ERASEBKGND()
	ON_BN_CLICKED(IDC_BUTTON_START, &CDlgCalibration::OnBnClickedButtonStart)
	ON_BN_CLICKED(IDC_BUTTON_EXIT, &CDlgCalibration::OnBnClickedButtonExit)
	ON_WM_RBUTTONDOWN()
	ON_WM_TIMER()
END_MESSAGE_MAP()

// CDlgCalibration 메시지 처리기입니다.

void CDlgCalibration::showWindow(BOOL bIsShow)
{
	CMtCtrlDlg *pParent = (CMtCtrlDlg *)GetParent();

	if (bIsShow)
	{
		CWnd::GetDesktopWindow()->GetWindowRect(m_rect);
		SetWindowPos(&wndTopMost, m_rect.left, m_rect.top, m_rect.right, m_rect.bottom, SWP_SHOWWINDOW);

		m_nCalibrationStep = CALIBRATION_NONE;
		GetDlgItem(IDC_BUTTON_START)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_BUTTON_EXIT)->ShowWindow(SW_SHOW);

		chageCurPoint(0);
	}
	else
	{
		BYTE bState = STATE_TOUCH;
		pParent->sendReportAll(CMD_SET_STATE, sizeof(bState), (LPBYTE)&bState);
	}

	ShowWindow(bIsShow ? SW_SHOW : SW_HIDE);
}

void CDlgCalibration::chageCurPoint(int nCurPoint)
{
	m_nScreenRadianIndex = nCurPoint;
	m_aryRadianSamples.RemoveAll();
	m_aryRadianSamples.FreeExtra();
	RedrawWindow();

	if (DATA_COEFFS_NUM == m_nScreenRadianIndex) {
		makeTransform();
		updateOrigin();

		m_nCalibrationStep = CALIBRATION_NONE;
		m_nScreenRadianIndex = 0;
		GetDlgItem(IDC_BUTTON_START)->ShowWindow(SW_SHOW);
		GetDlgItem(IDC_BUTTON_EXIT)->ShowWindow(SW_SHOW);
	} else {
		m_nCalibrationStep = CALIBRATION_WAIT;
		SetTimer(TID_WAIT, DELAY_WAIT, NULL);
	}
}


static const float X_LINES[4] = {
	PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SX),
	PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X1),
	PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X2),
	PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EX)
};
static const float Y_LINES[2] = {
	PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SY),
	PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EY)
};
static void point_x_position(float tan1, float tan2, float tan3, float x1, float x3, float y, PPOINT_FLOAT pPt)
{
	pPt->x = x1 + (x3 - x1) * (tan3 * (tan1 - tan2)) / (tan2 * (tan1 - tan3));
	pPt->y = y;
}
static void point_y_position(float tan1, float tan2, float tan3, float y1, float y3, float x, PPOINT_FLOAT pPt)
{
	pPt->x = x;
	pPt->y = y1 + (y3 - y1) * (tan2 - tan1) / (tan3 - tan1);
}
static int point_intersection(PPOINT_FLOAT p1, PPOINT_FLOAT p2, PPOINT_FLOAT p3, PPOINT_FLOAT p4, PPOINT_FLOAT pf)
{
	float d = (p1->x - p2->x) * (p3->y - p4->y) - (p1->y - p2->y) * (p3->x - p4->x);

	if (d) {
		float pre = (p1->x*p2->y - p1->y*p2->x);
		float post = (p3->x*p4->y - p3->y*p4->x);

		pf->x = (pre * (p3->x - p4->x) - (p1->x - p2->x) * post) / d;
		pf->y = (pre * (p3->y - p4->y) - (p1->y - p2->y) * post) / d;

		if ((0<=pf->x) && (1>=pf->x) && (0<=pf->y) && (1>=pf->y))
			return 1;
	}

	return 0;
}
static void radian_pointdata(PCAMERACONFIG_DATA pCCD, PRADIAN_DATA pRLeft, PRADIAN_DATA pRRight, PPOINT_DATA pPd)
{
	POINT_FLOAT fPtLeft[2]={0,}, fPtRight[2]={0,};
	float fCoeff;

	fCoeff = tanf(pRLeft->fCenter);
	if (pCCD[CAMERA_LEFT].fCoeffs[2] > fCoeff) {
		point_x_position(pCCD[CAMERA_LEFT].fCoeffs[2], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[3], X_LINES[2], X_LINES[3], Y_LINES[0], &fPtLeft[0]);
		point_y_position(pCCD[CAMERA_LEFT].fCoeffs[3], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[4], Y_LINES[0], Y_LINES[1], X_LINES[3], &fPtLeft[1]);
	} else if (pCCD[CAMERA_LEFT].fCoeffs[1] > fCoeff) {
		point_x_position(pCCD[CAMERA_LEFT].fCoeffs[1], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[2], X_LINES[1], X_LINES[2], Y_LINES[0], &fPtLeft[0]);
		point_y_position(pCCD[CAMERA_LEFT].fCoeffs[2], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[5], Y_LINES[0], Y_LINES[1], X_LINES[2], &fPtLeft[1]);
	} else if (pCCD[CAMERA_LEFT].fCoeffs[5] > fCoeff) {
		point_y_position(pCCD[CAMERA_LEFT].fCoeffs[1], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[6], Y_LINES[0], Y_LINES[1], X_LINES[1], &fPtLeft[0]);
		point_y_position(pCCD[CAMERA_LEFT].fCoeffs[2], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[5], Y_LINES[0], Y_LINES[1], X_LINES[2], &fPtLeft[1]);
	} else if (pCCD[CAMERA_LEFT].fCoeffs[6] > fCoeff) {
		point_y_position(pCCD[CAMERA_LEFT].fCoeffs[1], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[6], Y_LINES[0], Y_LINES[1], X_LINES[1], &fPtLeft[0]);
		point_x_position(pCCD[CAMERA_LEFT].fCoeffs[6], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[5], X_LINES[1], X_LINES[2], Y_LINES[1], &fPtLeft[1]);
	} else {
		point_y_position(pCCD[CAMERA_LEFT].fCoeffs[0], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[7], Y_LINES[0], Y_LINES[1], X_LINES[0], &fPtLeft[0]);
		point_x_position(pCCD[CAMERA_LEFT].fCoeffs[7], fCoeff, pCCD[CAMERA_LEFT].fCoeffs[6], X_LINES[0], X_LINES[1], Y_LINES[1], &fPtLeft[1]);
	}

	fCoeff = tanf(pRRight->fCenter);
	if (pCCD[CAMERA_RIGHT].fCoeffs[1] > fCoeff) {
		point_x_position(pCCD[CAMERA_RIGHT].fCoeffs[0], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[1], X_LINES[0], X_LINES[1], Y_LINES[0], &fPtRight[0]);
		point_y_position(pCCD[CAMERA_RIGHT].fCoeffs[0], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[7], Y_LINES[0], Y_LINES[1], X_LINES[0], &fPtRight[1]);
	} else if (pCCD[CAMERA_RIGHT].fCoeffs[2] > fCoeff) {
		point_x_position(pCCD[CAMERA_RIGHT].fCoeffs[1], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[2], X_LINES[1], X_LINES[2], Y_LINES[0], &fPtRight[0]);
		point_y_position(pCCD[CAMERA_RIGHT].fCoeffs[1], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[6], Y_LINES[0], Y_LINES[1], X_LINES[1], &fPtRight[1]);
	} else if (pCCD[CAMERA_RIGHT].fCoeffs[6] > fCoeff) {
		point_y_position(pCCD[CAMERA_RIGHT].fCoeffs[2], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[5], Y_LINES[0], Y_LINES[1], X_LINES[2], &fPtRight[0]);
		point_y_position(pCCD[CAMERA_RIGHT].fCoeffs[1], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[6], Y_LINES[0], Y_LINES[1], X_LINES[1], &fPtRight[1]);
	} else if (pCCD[CAMERA_RIGHT].fCoeffs[5] > fCoeff) {
		point_x_position(pCCD[CAMERA_RIGHT].fCoeffs[6], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[5], X_LINES[1], X_LINES[2], Y_LINES[1], &fPtRight[0]);
		point_y_position(pCCD[CAMERA_RIGHT].fCoeffs[2], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[5], Y_LINES[0], Y_LINES[1], X_LINES[2], &fPtRight[1]);
	} else {
		point_x_position(pCCD[CAMERA_RIGHT].fCoeffs[5], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[4], X_LINES[2], X_LINES[3], Y_LINES[1], &fPtRight[0]);
		point_y_position(pCCD[CAMERA_RIGHT].fCoeffs[3], fCoeff, pCCD[CAMERA_RIGHT].fCoeffs[4], Y_LINES[0], Y_LINES[1], X_LINES[3], &fPtRight[1]);
	}

	pPd->bIsValid = point_intersection(&fPtLeft[0], &fPtLeft[1], &fPtRight[0], &fPtRight[1], &pPd->fPt);
}
void CDlgCalibration::setRadianData(BYTE bCmd, BYTE bDev, BYTE bDLen, BYTE *pData)
{
	static RADIAN_DATA _RadianData[CAMERA_MAX_NUM][RADIAN_DATA_MAX_NUM] = {0,};
	static BYTE _bRadianData[CAMERA_MAX_NUM] = {0,};
	static BYTE _bRecvDevice = 0;
	CMtCtrlDlg *pParent = (CMtCtrlDlg *)GetParent();
	BYTE bIdx = bDev - DEV_CAMERA1;
	int nNewPoint = 0;

	if (CAMERA_MAX_NUM > bIdx) {
		int nCount = bDLen / sizeof(RADIAN_DATA);

		if (RADIAN_DATA_MAX_NUM >= nCount) {
			if (nCount)
				memcpy(&_RadianData[bIdx][0], pData, bDLen);
			_bRadianData[bIdx] = nCount;

			_bRecvDevice |= (1<<bIdx);
		}
	}
	if (((1<<CAMERA_RIGHT) | (1<<CAMERA_LEFT)) != _bRecvDevice) {
		return;
	}
	_bRecvDevice = 0;


	if (m_nCalibrationStep) {
		static DWORD _dwLastTime = 0;
		DWORD dwOffsetTime = GetTickCount() - _dwLastTime;
		_dwLastTime = GetTickCount();

		if (CALIBRATION_WAIT == m_nCalibrationStep) {
			return;
		}

		nNewPoint = min(_bRadianData[CAMERA_LEFT]*_bRadianData[CAMERA_RIGHT], POINT_DATA_MAX_NUM);
		if ((1 != nNewPoint) || (100 < dwOffsetTime)) {	// 100 mSec
			m_aryRadianSamples.RemoveAll();
			m_aryRadianSamples.FreeExtra();
			pParent->logMsg(("ERR (1 != nCount(%d))"), nNewPoint);
			return;
		}

		POINT_FLOAT ptTotal = {0,}, ptRadian = {_RadianData[CAMERA_LEFT][0].fCenter, _RadianData[CAMERA_RIGHT][0].fCenter};
		bIdx = m_nMovingAverageCount++ % MOVINGAVERAGE_NUM;

		m_ptMovingAverageSamples[bIdx].x = ptRadian.x;	//pPt[0].x;
		m_ptMovingAverageSamples[bIdx].y = ptRadian.y;	//pPt[0].y;
		bIdx = min(m_nMovingAverageCount, MOVINGAVERAGE_NUM);
		for (int i=0; i<bIdx; i++) {
			ptTotal.x += m_ptMovingAverageSamples[i].x;
			ptTotal.y += m_ptMovingAverageSamples[i].y;
		}
		ptRadian.x = ptTotal.x / bIdx;
		ptRadian.y = ptTotal.y / bIdx;

		if (RADIAN_NUM > m_aryRadianSamples.GetCount()) {
			m_aryRadianSamples.Add(ptRadian);
			return;
		}
		m_aryRadianSamples.RemoveAt(0);		// 오래된 데이터 삭제
		m_aryRadianSamples.Add(ptRadian);	// 새로운 데이터 추가
		for (int i=1, distErr=0; i<m_aryRadianSamples.GetCount(); i++) {
			float fOffsetX = fabs(m_aryRadianSamples.GetAt(0).x - m_aryRadianSamples.GetAt(i).x);
			float fOffsetY = fabs(m_aryRadianSamples.GetAt(0).y - m_aryRadianSamples.GetAt(i).y);
			if ((0.0003 < fOffsetX) || (0.0003 < fOffsetY)) {
				if (5 <= ++distErr) {
					m_aryRadianSamples.RemoveAll();
					m_aryRadianSamples.FreeExtra();
					pParent->logMsg(("ERR (offset : %f, %f)"), fOffsetX, fOffsetY);
					return;
				}
			} else {
				distErr = 0;
			}
		}

		ptTotal.x = ptTotal.y = 0;
		for (int i=0; i<RADIAN_NUM; i++) {
			ptTotal.x += m_aryRadianSamples.GetAt(i).x;
			ptTotal.y += m_aryRadianSamples.GetAt(i).y;
		}
		m_ptScreenRadians[m_nScreenRadianIndex].x = ptTotal.x / RADIAN_NUM;
		m_ptScreenRadians[m_nScreenRadianIndex].y = ptTotal.y / RADIAN_NUM;
		pParent->logMsg(("%d - %f,%f"), m_nScreenRadianIndex, m_ptScreenRadians[m_nScreenRadianIndex].x, m_ptScreenRadians[m_nScreenRadianIndex].y);
		{
			BYTE b10msec = 15;
			pParent->sendReport(CMD_SET_BUZZER, DEV_TOUCH, sizeof(b10msec), (LPBYTE)&b10msec);
		}

		chageCurPoint(m_nScreenRadianIndex + 1);
		m_nMovingAverageCount = 0;
	} else {
/*#undef	POINT_DATA_MAX_NUM
#define	POINT_DATA_MAX_NUM	(RADIAN_DATA_MAX_NUM*RADIAN_DATA_MAX_NUM)
#undef	TOUCH_DATA_MAX_NUM
#define	TOUCH_DATA_MAX_NUM	RADIAN_DATA_MAX_NUM*/

		POINT_DATA newPoints[POINT_DATA_MAX_NUM] = {0,};
		for (int l=0; l<min(_bRadianData[CAMERA_LEFT], TOUCH_DATA_MAX_NUM); l++) {
			for (int r=0; r<min(_bRadianData[CAMERA_RIGHT], TOUCH_DATA_MAX_NUM); r++) {
				if (POINT_DATA_MAX_NUM <= nNewPoint) {
					break;
				}
				radian_pointdata(pParent->m_CCD, &_RadianData[CAMERA_LEFT][l],
					&_RadianData[CAMERA_RIGHT][r], &newPoints[nNewPoint++]);
			}
		}

		if (nNewPoint) {
			CArray<POINT,POINT>	aryPoint;
			for (int i=0; i<nNewPoint; i++) {
				if (0 == newPoints[i].bIsValid) {
					continue;
				}

				POINT pt;
				pt.x = (int)(newPoints[i].fPt.x * m_rect.Width() + 0.5);
				pt.y = (int)(newPoints[i].fPt.y * m_rect.Height() + 0.5);
				aryPoint.Add(pt);
			}

			CClientDC dc(this);
			dc.Rectangle(m_rect);
			for (int i=0; i<aryPoint.GetCount(); i++) {
#if	1
				float fA, fB;
				int x, y;

				fA = (float)(aryPoint.GetAt(i).y - m_ptOrigin[CAMERA_LEFT].y) / (aryPoint.GetAt(i).x - m_ptOrigin[CAMERA_LEFT].x);
				fB = m_ptOrigin[CAMERA_LEFT].y - fA*m_ptOrigin[CAMERA_LEFT].x;
				if (aryPoint.GetAt(i).x < (int)(m_rect.Width()*PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X2))) {
					y = m_rect.Height();
					x = (int)((y - fB) / fA + 0.5);
				} else {
					x = m_rect.Width();
					y = (int)(fA*x + fB + 0.5);
				}
				dc.MoveTo(m_ptOrigin[CAMERA_LEFT].x, m_ptOrigin[CAMERA_LEFT].y);
				dc.LineTo(x, y);

				fA = (float)(aryPoint.GetAt(i).y - m_ptOrigin[CAMERA_RIGHT].y) / (aryPoint.GetAt(i).x - m_ptOrigin[CAMERA_RIGHT].x);
				fB = m_ptOrigin[CAMERA_RIGHT].y - fA*m_ptOrigin[CAMERA_RIGHT].x;
				if (aryPoint.GetAt(i).x > (int)(m_rect.Width()*PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X1))) {
					y = m_rect.Height();
					x = (int)((y - fB) / fA + 0.5);
				} else {
					x = 0;
					y = (int)(fA*x + fB + 0.5);
				}
				dc.MoveTo(m_ptOrigin[CAMERA_RIGHT].x, m_ptOrigin[CAMERA_RIGHT].y);
				dc.LineTo(x, y);
#else
				dc.MoveTo(m_ptOrigin[CAMERA_LEFT].x, m_ptOrigin[CAMERA_LEFT].y);
				dc.LineTo(aryPoint.GetAt(i).x, aryPoint.GetAt(i).y);
				dc.LineTo(m_ptOrigin[CAMERA_RIGHT].x, m_ptOrigin[CAMERA_RIGHT].y);

				CString strText;
				strText.Format(_T("%d"), i);
				dc.TextOut(aryPoint.GetAt(i).x, aryPoint.GetAt(i).y+10, strText);
#endif
			}
		} else {
			Invalidate();
		}
	}
}

void CDlgCalibration::makeTransform()
{
	CMtCtrlDlg *pParent = (CMtCtrlDlg *)GetParent();
	float fCoeffs[DATA_COEFFS_NUM] = {0,};

	for (int i=0; i<DATA_COEFFS_NUM; i++) {
		pParent->m_CCD[CAMERA_LEFT].fCoeffs[i] = fCoeffs[i] = tanf(m_ptScreenRadians[i].x);
		pParent->logMsg(("Left(%d) - %f"), i, fCoeffs[i]);
	}
	pParent->sendReport(CMD_SET_COEFFS, DEV_CAMERA1, sizeof(fCoeffs), (LPBYTE)&fCoeffs);

	for (int i=0; i<DATA_COEFFS_NUM; i++) {
		pParent->m_CCD[CAMERA_RIGHT].fCoeffs[i] = fCoeffs[i] = tanf(m_ptScreenRadians[i].y);
		pParent->logMsg(("Right(%d) - %f"), i, fCoeffs[i]);
	}
	pParent->sendReport(CMD_SET_COEFFS, DEV_CAMERA2, sizeof(fCoeffs), (LPBYTE)&fCoeffs);
}

void CDlgCalibration::updateOrigin()
{
	CMtCtrlDlg *pParent = (CMtCtrlDlg *)GetParent();
	float *pCoeffs;
	POINT_FLOAT fPt1, fPt2, fPt3, fPt4, fOrg;

	pCoeffs = pParent->m_CCD[CAMERA_LEFT].fCoeffs;
	point_y_position(pCoeffs[1], pCoeffs[4], pCoeffs[6], Y_LINES[0], Y_LINES[1], X_LINES[1], &fPt1);
	point_y_position(pCoeffs[2], pCoeffs[4], pCoeffs[5], Y_LINES[0], Y_LINES[1], X_LINES[2], &fPt2);
	point_y_position(pCoeffs[1], pCoeffs[5], pCoeffs[6], Y_LINES[0], Y_LINES[1], X_LINES[1], &fPt3);
	point_x_position(pCoeffs[6], pCoeffs[5], pCoeffs[5], X_LINES[1], X_LINES[2], Y_LINES[1], &fPt4);
	point_intersection(&fPt1, &fPt2, &fPt3, &fPt4, &fOrg);
	m_ptOrigin[CAMERA_LEFT].x = (int)(fOrg.x * m_rect.Width() + 0.5);
	m_ptOrigin[CAMERA_LEFT].y = (int)(fOrg.y * m_rect.Height() + 0.5);

	pCoeffs = pParent->m_CCD[CAMERA_RIGHT].fCoeffs;
	point_y_position(pCoeffs[2], pCoeffs[7], pCoeffs[5], Y_LINES[0], Y_LINES[1], X_LINES[2], &fPt1);
	point_y_position(pCoeffs[1], pCoeffs[7], pCoeffs[6], Y_LINES[0], Y_LINES[1], X_LINES[1], &fPt2);
	point_x_position(pCoeffs[6], pCoeffs[6], pCoeffs[5], X_LINES[1], X_LINES[2], Y_LINES[1], &fPt3);
	point_y_position(pCoeffs[2], pCoeffs[6], pCoeffs[5], Y_LINES[0], Y_LINES[1], X_LINES[2], &fPt4);
	point_intersection(&fPt1, &fPt2, &fPt3, &fPt4, &fOrg);
	m_ptOrigin[CAMERA_RIGHT].x = (int)(fOrg.x * m_rect.Width() + 0.5);
	m_ptOrigin[CAMERA_RIGHT].y = (int)(fOrg.y * m_rect.Height() + 0.5);
}


BOOL CDlgCalibration::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  여기에 추가 초기화 작업을 추가합니다.
	CWnd::GetDesktopWindow()->GetWindowRect(m_rect);
	SetWindowPos(&wndTopMost, m_rect.left, m_rect.top, m_rect.right, m_rect.bottom, SWP_SHOWWINDOW);

	{
		const int WIDTH=120, HEIGHT=40;
		int nWCenter = m_rect.Width() / 2;
		int nHCenter = m_rect.Height() / 2;
		CRect rect;

		rect.SetRect(nWCenter-10-WIDTH, nHCenter-HEIGHT/2, nWCenter-10, nHCenter+HEIGHT/2);
		GetDlgItem(IDC_BUTTON_START)->MoveWindow(rect);

		rect.SetRect(nWCenter+10, nHCenter-HEIGHT/2, nWCenter+10+WIDTH, nHCenter+HEIGHT/2);
		GetDlgItem(IDC_BUTTON_EXIT)->MoveWindow(rect);
	}

	m_ptScreens[0].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SX) + 0.5);
	m_ptScreens[0].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SY) + 0.5);

	m_ptScreens[1].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X1) + 0.5);
	m_ptScreens[1].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SY) + 0.5);

	m_ptScreens[2].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X2) + 0.5);
	m_ptScreens[2].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SY) + 0.5);

	m_ptScreens[3].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EX) + 0.5);
	m_ptScreens[3].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SY) + 0.5);

	m_ptScreens[4].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EX) + 0.5);
	m_ptScreens[4].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EY) + 0.5);

	m_ptScreens[5].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X2) + 0.5);
	m_ptScreens[5].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EY) + 0.5);

	m_ptScreens[6].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_X1) + 0.5);
	m_ptScreens[6].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EY) + 0.5);

	m_ptScreens[7].x = (int)(m_rect.Width() *  PERCENT_TO_POINT(DATA_COEFFS_MARGIN_SX) + 0.5);
	m_ptScreens[7].y = (int)(m_rect.Height() * PERCENT_TO_POINT(DATA_COEFFS_MARGIN_EY) + 0.5);

	updateOrigin();

	return TRUE;  // return TRUE unless you set the focus to a control
	// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}

void CDlgCalibration::OnDestroy()
{
	CDialogEx::OnDestroy();

	// TODO: 여기에 메시지 처리기 코드를 추가합니다.
}

BOOL CDlgCalibration::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
	if (WM_KEYDOWN == pMsg->message)
	{
		if (VK_RETURN == pMsg->wParam)
		{
			showWindow(FALSE);
			return TRUE;
		}
		else if (VK_ESCAPE == pMsg->wParam)
		{
			showWindow(FALSE);
			return TRUE;
		}
	}

	return CDialogEx::PreTranslateMessage(pMsg);
}

BOOL CDlgCalibration::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
	//return TRUE;
	return CDialogEx::OnEraseBkgnd(pDC);
}
void CDlgCalibration::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: 여기에 메시지 처리기 코드를 추가합니다.
	// 그리기 메시지에 대해서는 CDialogEx::OnPaint()을(를) 호출하지 마십시오.
	CMemDC2 MemDC(&dc, &m_rect);
	MemDC.Rectangle(m_rect);

	CPen defPen(PS_SOLID, 1, RGB(0x00,0x00,0x00)), curPen(PS_SOLID, 2, RGB(0xFF,0x00,0x00)), *pOldPen;

	pOldPen = MemDC.SelectObject(&defPen);

	if (m_nCalibrationStep) {
		for (int i=0; i<DATA_COEFFS_NUM; i++)
		{
			if (m_nScreenRadianIndex == i)
				MemDC.SelectObject(&curPen);
			else
				MemDC.SelectObject(&defPen);

			MemDC.MoveTo(m_ptScreens[i].x - 20, m_ptScreens[i].y);
			MemDC.LineTo(m_ptScreens[i].x + 20, m_ptScreens[i].y);

			MemDC.MoveTo(m_ptScreens[i].x, m_ptScreens[i].y - 20);
			MemDC.LineTo(m_ptScreens[i].x, m_ptScreens[i].y + 20);
		}
	}

	MemDC.SelectObject(pOldPen);
}

void CDlgCalibration::OnBnClickedButtonStart()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	m_nCalibrationStep = CALIBRATION_READ;
	GetDlgItem(IDC_BUTTON_START)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_BUTTON_EXIT)->ShowWindow(SW_HIDE);
	Invalidate();
}

void CDlgCalibration::OnBnClickedButtonExit()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	showWindow(FALSE);
}

void CDlgCalibration::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
	showWindow(FALSE);
	CDialogEx::OnRButtonDown(nFlags, point);
}


void CDlgCalibration::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
	if (TID_WAIT == nIDEvent) {
		KillTimer(nIDEvent);
		m_nCalibrationStep = CALIBRATION_READ;
	}

	CDialogEx::OnTimer(nIDEvent);
}
